#include <vector>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <functional>
#include "threadpool.hpp"

using task_t = function<void()>;

class CommunicationMod
{
private:
    std::vector<struct sockaddr_in>::iterator find(struct sockaddr_in* srcaddr)
    {
        for (auto it = _clientinfo.begin(); it != _clientinfo.end(); it++)
        {
            if (srcaddr->sin_addr.s_addr == it->sin_addr.s_addr && srcaddr->sin_port == it->sin_port)
                return it;
        }
        return _clientinfo.end();
    }

    void addUser(struct sockaddr_in* srcaddr)
    {
        if (find(srcaddr) == _clientinfo.end())
            _clientinfo.emplace_back(*srcaddr);
    }

    void delUser(struct sockaddr_in* srcaddr)
    {
        auto it = find(srcaddr);
        if (it != _clientinfo.end())
            _clientinfo.erase(it);
    }

    void spread(int sockfd, struct sockaddr_in srcaddr, string msg)
    {
        LockGuard lg(_mutex); //多线程情况下_clientinfo也是共享资源，也要加锁保护

        addUser(&srcaddr); // 直接采用网络序存放

        //将消息转发给所有用户
        for(auto& e : _clientinfo)
        {
            sendto(sockfd, msg.c_str(), msg.size(), 0, (struct sockaddr*)&e, sizeof(e));
        }
        LOG(INFO, "send message to everyone:total is %d", _clientinfo.size());
        if (msg == "q" || msg == "quit")
            delUser(&srcaddr);
    }

public:
    CommunicationMod()
    {
        pthread_mutex_init(&_mutex, nullptr);
    }

    void spreadInfo(int sockfd, struct sockaddr_in& srcaddr, string msg)
    {
        task_t t = std::bind(&CommunicationMod::spread, this, sockfd, srcaddr, msg);
        ThreadPool<task_t>::getInstance()->push(t); //每当一个用户发送来消息的时候，就让线程池里的一个线程去转发此消息给所有人
    }

    ~CommunicationMod()
    {
        pthread_mutex_destroy(&_mutex);
        ThreadPool<task_t>::getInstance()->stop();
    }

private:
    std::vector<struct sockaddr_in> _clientinfo;
    pthread_mutex_t _mutex;
};